<template>
    <div class="forget-password">
        <el-steps :active="state.active" align-center>
            <el-step
                v-for="n in 3"
                :key="n"
                :icon="icons[n - 1] || DefaultStepIcons[n - 1]"
                :title="titles[n - 1] || DefaultStepTitles[n - 1]"
            />
        </el-steps>
        <el-form v-if="[0, 1].includes(state.active)" ref="formRef" :model="form" :rules="rules">
            <template v-if="state.active === 0">
                <el-form-item prop="phone">
                    <el-input v-model="form.phone" placeholder="请输入手机号码" prefix-icon="el-icon-user" clearable />
                </el-form-item>
                <el-form-item prop="code">
                    <el-input
                        v-model="form.code"
                        placeholder="请输入验证码"
                        maxlength="6"
                        prefix-icon="el-icon-message"
                        clearable
                    >
                        <template #append>
                            <el-button :disabled="state.disabled" link @click="handleGetCode">
                                {{ state.codeText }}
                            </el-button>
                        </template>
                    </el-input>
                </el-form-item>
            </template>
            <template v-if="state.active === 1">
                <Password ref="passwordRef" v-model="form.password" />
                <el-form-item prop="passwordConfirm">
                    <el-input
                        v-model="form.passwordConfirm"
                        type="password"
                        show-password
                        placeholder="请再次输入密码"
                        prefix-icon="el-icon-lock"
                        clearable
                    />
                </el-form-item>
            </template>
            <el-form-item>
                <el-button class="btn-next" type="primary" @click="handleNext">下一步</el-button>
            </el-form-item>
        </el-form>
        <div v-if="state.active === 2" class="success-content">
            <img :src="IconSuccess" alt="" />
            <h3>恭喜您！密码重置成功</h3>
            <p v-if="props.autoRedirect">{{ state.left }}s后自动跳转至{{ props.text }}</p>
            <el-button class="btn-next" type="primary" @click="handleRedirect">立即跳转</el-button>
        </div>
        <Captcha
            ref="captchaRef"
            v-model:disabled="state.disabled"
            v-model:text="state.codeText"
            unique-key="forget-password"
            keep-running
            :duration="props.smsDelay"
        />
    </div>
</template>

<script setup>
import { computed, reactive, ref } from "vue";
import { useRouter } from "vue-router";

import Password from "@/components/password/index.vue";
import Captcha from "@/components/captcha.vue";

import { DefaultStepTitles, DefaultStepIcons, IconSuccess } from "./const";

const router = useRouter();

const props = defineProps({
    titles: { type: Array, default: () => [] },
    icons: { type: Array, default: () => [] },
    smsDelay: { type: [String, Number], required: true },
    getSmsCode: { type: Function, required: true },
    reset: { type: Function, required: true },
    autoRedirect: { type: Boolean, default: true },
    link: { type: String, default: "/login" },
    delay: { type: [String, Number], default: 60 },
    text: { type: String, default: "登录页" },
});

const captchaRef = ref(null);
const formRef = ref(null);
const passwordRef = ref(null);
const form = reactive({ phone: "", code: "", password: "", passwordConfirm: "" });
const state = reactive({ active: 0, disabled: false, codeText: "", left: 0, timer: null });

const titles = computed(() => (props.titles && props.titles.length ? props.titles : []));
const icons = computed(() => (props.icons && props.icons.length ? props.icons : []));

const rules = {
    phone: [
        { required: true, message: "请输入手机号码" },
        {
            validator: async (_, value) =>
                /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(value)
                    ? Promise.resolve()
                    : Promise.reject("手机号格式不正确"),
        },
    ],
    code: [
        { required: true, message: "请输入验证码" },
        { len: 6, message: "请输入6位数验证码" },
    ],
    passwordConfirm: [
        { required: true, message: "请再次输入密码" },
        { validator: (_, value) => value === form.password, message: "两次输入密码必须保持一致，请重新输入" },
    ],
};

const count = () => {
    state.left--;
    if (state.left >= 0) {
        state.timer = setTimeout(count, 1000);
    } else {
        clearTimeout(state.timer);
        handleRedirect();
    }
};

const resetPasswordCallback = (status) => {
    if (!status) return;

    state.active = 2;

    if (props.autoRedirect) {
        state.left = props.delay;
        count();
    }
};

const getSmsCodeCallback = (status) => {
    if (status) {
        captchaRef.value.start();
    }
};

const handleGetCode = async () => {
    const checkPhone = await formRef.value.validateField("phone").catch(() => {});
    if (!checkPhone) return;

    if (captchaRef.value.disabled) return;

    const fn = props.getSmsCode(form.phone, getSmsCodeCallback);
    let status = null;

    if (fn instanceof Promise) {
        status = await fn;
        if (status !== void 0) getSmsCodeCallback(status);
    }
};

const handleRedirect = () => router.push(props.link);

const handleNext = async () => {
    const fns = [passwordRef.value?.validate(), formRef.value.validate()];
    const status = await Promise.all(fns).catch(() => {});
    if (!status) return;

    if (state.active === 1) {
        const params = { ...form };
        delete params.passwordConfirm;

        const fn = props.reset(params, resetPasswordCallback);
        let status = null;

        if (fn instanceof Promise) {
            status = await fn;
            if (status !== void 0) resetPasswordCallback(status);
        }
    } else {
        state.active++;
    }
};
</script>

<style lang="scss" scoped>
.forget-password {
    width: 584px;
    padding: 48px 18px;
    box-sizing: border-box;
    background: #fff;
    :deep() {
        .el-form {
            width: 320px;
            margin: 42px auto 0;
        }
        .el-step {
            %active {
                &.is-finish,
                &.is-process {
                    font-weight: normal;
                    color: var(--el-color-primary);
                    border-color: var(--el-color-primary);
                }
                &.is-finish {
                    .el-step__line {
                        background: var(--el-color-primary);
                    }
                }
            }
            .el-step__head {
                @extend %active;
            }
            .el-step__title {
                @extend %active;
            }
        }
    }
    .success-content {
        display: flex;
        flex-direction: column;
        align-items: center;
        width: 320px;
        margin: 42px auto 0;
        img {
            margin-bottom: 24px;
        }
        h3 {
            line-height: 30px;
            font-size: 20px;
            text-align: center;
            color: rgba($color: #000000, $alpha: 0.85);
        }
        p {
            line-height: 22px;
            font-size: 14px;
            color: rgba(0, 0, 0, 0.65);
            text-align: center;
            margin: 12px 0 24px;
        }
    }
    .btn-next {
        width: 100%;
    }
}
</style>
